package com.ethercamp.harmony.dmt.db.config;

import com.ethercamp.harmony.dmt.db.api.BlockAPI;
import com.ethercamp.harmony.dmt.db.api.impl.mongo.BlockAPIMongoImpl;
import com.ethercamp.harmony.dmt.db.core.BlockCache;
import com.ethercamp.harmony.dmt.db.dao.MongoTemplateFactory;
import com.ethercamp.harmony.dmt.db.handler.AccountObserver;
import com.ethercamp.harmony.dmt.db.handler.BlockObserver;
import com.ethercamp.harmony.dmt.db.handler.TransactionObserver;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.*;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;

import java.util.Arrays;

/**
 * @author Matthew丶钟
 */
@Configuration
@ComponentScan("com.ethercamp.harmony.dmt.db")
public class AppConfig {

    private final Logger logger = LoggerFactory.getLogger("AppConfig");


    private static EthersqlConfig config = EthersqlConfig.getDefaultConfig();

    private Boolean resetDataBase;

    private static BlockCache blockCache = new BlockCache();

    static{
        blockCache.addObserver(transactionObserver());
        blockCache.addObserver(accountObserver());
        blockCache.addObserver(blockObserver());
    }

    public AppConfig(){
        this.resetDataBase = config.getResetDatabase();
    }

    public AppConfig(Boolean resetDataBase){
        this.resetDataBase = resetDataBase;
    }

    @Bean
    @Lazy
    public static MongoDbFactory mongoDbFactory() {
        return new SimpleMongoDbFactory(mongoClient(), config.getMongoDatabase());
    }

    @Bean
    @Lazy
    public static MongoClient mongoClient() {
        if(config.getMongoUsername() != null){
            MongoCredential credential = MongoCredential.createCredential(config.getMongoUsername(), config.getMongoDatabase(), config.getMongoPassword().toCharArray());
            return new MongoClient(new ServerAddress(config.getMongoHost(), config.getMongoPort()), Arrays.asList(credential));
        }
        return new MongoClient(config.getMongoHost(), config.getMongoPort());
    }

    @Bean
    public static MongoTemplateFactory mongoTemplateFactory() {
        return new MongoTemplateFactory(mongoDbFactory());
    }

    @Bean
    @Scope("prototype")
    public static BlockObserver blockObserver() {
        return new BlockObserver(mongoTemplateFactory());
    }

    @Bean
    @Scope("prototype")
    public static TransactionObserver transactionObserver() {
        return new TransactionObserver(mongoTemplateFactory());
    }

    @Bean
    @Scope("prototype")
    public static AccountObserver accountObserver() {
        return new AccountObserver(mongoTemplateFactory());
    }

    @Bean
    @Scope("prototype")
    public static BlockAPI blockAPI() {
        return new BlockAPIMongoImpl(new MongoTemplate(mongoDbFactory()));
    }

    @Bean
    @Scope("singleton")
    public BlockCache blockCache() {
        return blockCache;
    }

//    @Bean
//    @Scope("singleton")
//    public EthereumBean ethereumBean() {
//        EthereumBean ethereumBean = new EthereumBean(blockCache());
//        ethereumBean.start();
//        return ethereumBean;
//    }

//    @Bean
//    public Initializer initializer() {
//        return new Initializer(new MongoTemplate(mongoDbFactory()));
//    }

    /**
     * 初始化数据库连接
     * @return
     */
    @Bean
    public Initializer initializer() {
        return new Initializer(blockObserver(),transactionObserver(),accountObserver());
    }
}
